<script setup lang="ts">
import { reactive, ref, onMounted, onUnmounted } from 'vue'
import type { FormInstance, FormRules } from 'element-plus'
import { ElNotification, ElMessageBox } from 'element-plus'
import { getMaterialList, addMaterial, updateMaterial, deleteMaterial } from '@/axios/api/package-material/basic'
import useUserStore from '@/store/user'
import * as XLSX from 'xlsx';
//@ts-ignore
import { throttle } from 'lodash'; // 防抖函数

interface ApiResponse<T> {
  code: number
  data: T
  message?: string
}

interface TableItem {
  code: string
  type: string
  description: string
  unit: string
  createTime: string
  creator: string
  currentStock: number
}

const formRef = ref<FormInstance>()
const dialogVisible = ref(false)
const searchInput = ref('')
const dialogTitle = ref('新增包材')
const isEdit = ref(false)

const form = reactive({
  code: '',
  type: '',
  description: '',
  unit: ''
})

const tableData = ref<TableItem[]>([])

const rules = reactive<FormRules>({
  code: [
    { required: true, message: '请输入编码', trigger: 'blur' },
    { min: 3, max: 20, message: '长度在 3 到 20 个字符', trigger: 'blur' }
  ],
  type: [
    { required: true, message: '请输入类型', trigger: 'blur' }
  ],
  description: [
    { required: true, message: '请输入描述', trigger: 'blur' }
  ],
  unit: [
    { required: true, message: '请输入单位', trigger: 'blur' }
  ]
})

// 添加分页相关的状态
const currentPage = ref(1)
const pageSize = ref(10)
const total = ref(0)

// 表格高度
const tableHeight = ref(window.innerHeight - 64 - 40 - 51 - 52 - 72 - 20 - 64)

// 更新表格高度
const updateTableHeight = () => {
  tableHeight.value = window.innerHeight - 64 - 40 - 51 - 52 - 72 - 20 - 64
}

// 获取列表数据
const fetchData = async () => {
  try {
    const params = {
      search: searchInput.value,
      page: currentPage.value,
      page_size: pageSize.value
    }
    const response = await getMaterialList(params) as unknown as ApiResponse<{
      records: TableItem[]
      total: number
    }>
    if (response.code === 200) {
      tableData.value = response.data.records
      total.value = response.data.total
    }
  } catch (error) {
    ElNotification({
      title: '错误',
      message: '获取数据失败',
      type: 'error',
    })
  }
}

// 处理页码改变
const handleCurrentChange = (val: number) => {
  currentPage.value = val
  fetchData()
}

// 处理每页条数改变
const handleSizeChange = (val: number) => {
  pageSize.value = val
  currentPage.value = 1
  fetchData()
}

// 提交表单
const submitForm = async (formEl: FormInstance | undefined) => {
  if (!formEl) return
  await formEl.validate(async (valid) => {
    if (valid) {
      try {
        const userStore = useUserStore()
        const res = await (isEdit.value ? updateMaterial({
          ...form,
          operator: userStore.username
        }) : addMaterial({
          ...form,
          operator: userStore.username
        })) as unknown as ApiResponse<any>
        if (res.code === 200) {
          ElNotification({
            title: '成功',
            message: isEdit.value ? '修改成功' : '新增成功',
            type: 'success',
          })
          dialogVisible.value = false
          formEl.resetFields()
          fetchData() // 刷新列表
        }
      } catch (error) {
        ElNotification({
          title: '错误',
          message: isEdit.value ? '修改失败' : '新增失败',
          type: 'error',
        })
      }
    }
  })
}

// 防抖处理的方法
const throttleHandleSearch = throttle(() => {
  currentPage.value = 1
  fetchData()
}, 1000, {
  leading: true,
  trailing: false
})

const throttleResetSearch = throttle(() => {
  searchInput.value = ''
  currentPage.value = 1
  fetchData()
}, 1000, {
  leading: true,
  trailing: false
})

const throttleHandleExportAll = throttle(async () => {
  try {
    const params = {
      search: searchInput.value,
      page: 1,
      page_size: total.value
    }
    const response = await getMaterialList(params) as unknown as ApiResponse<{
      records: TableItem[]
      total: number
    }>
    if (response.code === 200) {
      exportExcel(response.data.records)
    }
  } catch (error) {
    ElNotification({
      title: '错误',
      message: '导出数据失败',
      type: 'error',
    })
  }
}, 1000, {
  leading: true,
  trailing: false
})

const throttleHandleAdd = throttle(() => {
  isEdit.value = false
  dialogTitle.value = '新增包材'
  Object.keys(form).forEach(key => {
    form[key as keyof typeof form] = ''
  })
  dialogVisible.value = true
}, 1000, {
  leading: true,
  trailing: false
})

const throttleHandleEdit = throttle((row: TableItem) => {
  isEdit.value = true
  dialogTitle.value = '编辑包材'
  Object.keys(form).forEach(key => {
    const value = row[key as keyof TableItem]
    if (typeof value === 'string') {
      form[key as keyof typeof form] = value
    }
  })
  dialogVisible.value = true
}, 1000, {
  leading: true,
  trailing: false
})

const throttleHandleDelete = throttle((row: TableItem) => {
  ElMessageBox.confirm(
    `确认删除编码为 ${row.code} 的包材吗？`,
    '删除确认',
    {
      confirmButtonText: '确认',
      cancelButtonText: '取消',
      type: 'warning',
    }
  )
    .then(async () => {
      try {
        const userStore = useUserStore()
        const res = await deleteMaterial(row.code, userStore.username) as unknown as ApiResponse<any>
        if (res.code === 200) {
          ElNotification({
            title: '成功',
            message: `删除成功：${row.code}`,
            type: 'success',
          })
          fetchData()
        }
      } catch (error) {
        ElNotification({
          title: '错误',
          message: '删除失败',
          type: 'error',
        })
      }
    })
    .catch(() => {
      // 取消删除操作
    })
}, 1000, {
  leading: true,
  trailing: false
})

// 初始化
onMounted(() => {
  fetchData()
  // 添加窗口大小变化监听
  window.addEventListener('resize', updateTableHeight)
})

// 组件卸载时移除监听器
onUnmounted(() => {
  window.removeEventListener('resize', updateTableHeight)
})

// 导出excel
const exportExcel = async (tableData: TableItem[]) => {
        if (tableData.length == 0) {
            ElNotification({
                title: 'Error',
                message: '没有数据',
                type: 'error',
            })
            return;
        }

        const ws = XLSX.utils.json_to_sheet(tableData); // 将数据转换为工作表
        const wb = { Sheets: { 'Data': ws }, SheetNames: ['Data'] }; // 创建工作簿
        const excelBuffer = XLSX.write(wb, { bookType: 'xlsx', type: 'array' }); // 将工作簿转化为二进制缓冲区

        // 创建Blob对象并使用URL.createObjectURL方法生成URL
        const data = new Blob([excelBuffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8' });
        const url = URL.createObjectURL(data);

        // 创建隐藏的可下载链接
        const link = document.createElement('a');
        link.href = url;
        link.style.display = 'none';
        link.download = 'data.xlsx'; // 设置下载文件名
        document.body.appendChild(link);

        // 触发点击下载
        link.click();
        // 清理
        setTimeout(() => {
            document.body.removeChild(link);
            window.URL.revokeObjectURL(url);
        }, 100);
    }
</script>

<template>
  <div class="container">
    <el-card class="box-card">
      <template #header>
        <div class="card-header">
          <span class="title">基表维护</span>
          <div class="button-group">
            <el-button type="primary" @click="throttleHandleExportAll">导出Excel</el-button>
            <el-button type="primary" @click="throttleHandleAdd" v-has="`btn_add_package_material`">新增包材</el-button>
          </div>
        </div>
      </template>

      <div class="search-bar">
        <el-input
          v-model="searchInput"
          placeholder="请输入编码或类型搜索"
          class="search-input"
          clearable
        >
          <template #prefix>
            <el-icon><Search /></el-icon>
          </template>
        </el-input>
        <el-button type="primary" @click="throttleHandleSearch">搜索</el-button>
        <el-button @click="throttleResetSearch">重置</el-button>
      </div>

      <el-table 
        :data="tableData" 
        style="width: 100%" 
        border 
        stripe
        :height="tableHeight"
      >
        <el-table-column prop="code" label="编码" width="120" />
        <el-table-column prop="type" label="类型" width="120" />
        <el-table-column prop="description" label="描述" />
        <el-table-column prop="unit" label="单位" width="80" />
        <el-table-column prop="currentStock" label="当前库存" width="100" />
        <el-table-column prop="creator" label="创建人" width="120" />
        <el-table-column prop="createTime" label="创建时间" width="180">
          <template #default="scope">
            {{ new Date(scope.row.createTime).toLocaleString('zh-CN', {
              year: 'numeric',
              month: '2-digit',
              day: '2-digit',
              hour: '2-digit',
              minute: '2-digit',
              second: '2-digit',
              hour12: false
            }).replace(/\//g, '-') }}
          </template>
        </el-table-column>
        <el-table-column label="操作" width="180" fixed="right">
          <template #default="scope">
            <el-button 
              link 
              type="primary" 
              size="small"
              @click="throttleHandleEdit(scope.row)"
              v-has="`btn_edit_package_material`"
            >
              <el-icon><Edit /></el-icon>
              编辑
            </el-button>
            <el-button 
              link 
              type="danger" 
              size="small"
              @click="throttleHandleDelete(scope.row)"
              v-has="`btn_delete_package_material`"
            >
              <el-icon><Delete /></el-icon>
              删除
            </el-button>
          </template>
        </el-table-column>
      </el-table>

      <div class="pagination">
        <el-pagination
          background
          layout="total, sizes, prev, pager, next"
          :total="total"
          :page-size="pageSize"
          :current-page="currentPage"
          :page-sizes="[10, 20, 50, 100]"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
        />
      </div>
    </el-card>

    <el-dialog
      v-model="dialogVisible"
      :title="dialogTitle"
      width="500px"
      destroy-on-close
    >
      <el-form
        ref="formRef"
        :model="form"
        :rules="rules"
        label-width="100px"
        class="demo-ruleForm"
        status-icon
      >
        <el-form-item label="编码" prop="code">
          <el-input 
            v-model="form.code" 
            :disabled="isEdit"
            :placeholder="isEdit ? '' : '请输入编码'"
          />
        </el-form-item>

        <el-form-item label="类型" prop="type">
          <el-input 
            v-model="form.type" 
            placeholder="请输入类型"
          />
        </el-form-item>

        <el-form-item label="描述" prop="description">
          <el-input v-model="form.description" type="textarea" :rows="3" />
        </el-form-item>

        <el-form-item label="单位" prop="unit">
          <el-input 
            v-model="form.unit" 
            placeholder="请输入单位"
          />
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="dialogVisible = false">取消</el-button>
          <el-button type="primary" @click="submitForm(formRef)">
            {{ isEdit ? '保存' : '确认' }}
          </el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<style scoped>
.container {
  padding: 20px;
}

.box-card {
  width: 100%;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.button-group {
  display: flex;
  gap: 10px;
}

.title {
  font-size: 18px;
  font-weight: bold;
}

.search-bar {
  margin-bottom: 20px;
  display: flex;
  gap: 10px;
  align-items: center;
}

.search-input {
  width: 300px;
}

.pagination {
  margin-top: 20px;
  display: flex;
  justify-content: flex-end;
}

.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}

:deep(.el-card__header) {
  padding: 15px 20px;
  border-bottom: 1px solid var(--el-border-color-light);
  background-color: var(--el-color-primary-light-9);
}

:deep(.el-button) {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
</style> 